<?php
namespace Zxf5115\Laravel\Kernel\Traits;

use InvalidArgumentException;
use Illuminate\Database\Eloquent\Builder;
use Zxf5115\Laravel\Kernel\Builders\WithBuilder;
use Zxf5115\Laravel\Kernel\Builders\FieldBuilder;
use Zxf5115\Laravel\Kernel\Builders\WhereBuilder;

/**
 * @author zhangxiaofei [<1326336909@qq.com>]
 * @dateTime 2025-09-28
 *
 * 数据库查询特征类
 */
trait QueryTrait
{
  /**
   * 批量添加排序条件
   *
   * @param Builder $query 查询构建器实例
   * @param array $sortRules 排序规则数组，格式：[['key' => '字段名', 'value' => 'asc|desc'], ...]
   * @return 查询构建器对象
   */
  public function scopeOrder(Builder $query, array $sortRules) : Builder
  {
    foreach($sortRules as $index => $rule)
    {
      // 验证排序规则格式
      if(!isset($rule['key'], $rule['value']) || !in_array(strtolower($rule['value']), ['asc', 'desc']))
      {
        throw new InvalidArgumentException("排序规则格式错误，索引: {$index}");
      }

      $query->orderBy($rule['key'], $rule['value']);
    }

    return $query;
  }


  /**
   * 执行分页查询并返回过滤后的结果
   *
   * @param Builder $query 查询构建器实例
   * @param int $pageSize 每页显示数量
   * @param array $keepKeys 需要保留的分页字段，默认：total, per_page, current_page, last_page, data
   * @return array 查询结果
   */
  public function scopePaging(Builder $query, int $pageSize = 10, array $keepKeys = ['total', 'per_page', 'current_page', 'last_page', 'data']) : array
  {
    $response = $query->paginate($pageSize)->toArray();

    return array_intersect_key($response, array_flip($keepKeys));
  }


  /**
   * 提取指定字段数据，支持单字段或键值对形式
   *
   * @param Builder $query 查询构建器实例
   * @param array $params 请求参数
   * @param bool $isArray 是否将返回内容转换为数组
   * @return Collection|array 查询结果
   */
  public function scopePluck(Builder $query, string|array $params = 'id', bool $isArray = false) : Collection|array
  {
    // 处理数组参数（必须包含2个元素）
    if(is_array($params))
    {
      if(count($params) !== 2)
      {
        throw new InvalidArgumentException("数组参数必须包含2个元素：[值字段, 键字段]");
      }

      $response = $query->pluck($params[0], $params[1]);
    }
    else
    {
      $response = $query->pluck($params);
    }

    return $isArray ? $response->toArray() : $response;
  }


  /**
   * 构建查询条件
   *
   * @param Builder $query 查询构建器实例
   * @param array $serviceParams 服务类可以访问参数
   * @param string $relationName 请求参数数组
   * @return Builder 查询构建器实例
   */
  public function scopeWhereBuild(Builder $query, array $serviceParams, array $params) : Builder
  {
    // 构建查询条件
    WhereBuilder::myself($query, $serviceParams)->buildWhere($params);

    return $query;
  }


  /**
   * 构建关联查询
   *
   * @param Builder $query 查询构建器实例
   * @param array $withArray 关联对象数组
   * @param string $relationName 关联场景名称
   * @return Builder 查询构建器实例
   */
  public function scopeWithBuild(Builder $query, $withArray, string $relationName) : Builder
  {
    // 构建关联查询
    WithBuilder::myself($query)->buildWith($withArray, $relationName);

    return $query;
  }


  /**
   * 构建查询字段
   *
   * @param Builder $query 查询构建器实例
   * @param array $fieldParams 查询字段参数
   * @param string $relationName 关联场景名称
   * @return Builder 查询构建器实例
   */
  public function scopeFieldBuild(Builder $query, $fieldParams, string $relationName) : Builder
  {
    // 构建查询字段参数
    FieldBuilder::myself($query)->buildField($fieldParams, $relationName);

    return $query;
  }
}
